package com.jkgh.remedium.rsgen.generator.flash;

import java.io.PrintStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.jkgh.remedium.rsgen.vo.Argument;

public class RemediumArgumentConsumerFlashGenerator {

	private static interface Handler {

		public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending);
	}

	private static class ObjectHandler implements Handler {

		private final String type;

		public ObjectHandler(String type) {

			this.type = type;
		}

		@Override
		public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

			intent(out, intent, "remedium.setState(" + type + ".createConsumingState(remedium, message, function(" + name + number + ":" + type + "):void {");
			generate(out, intent + 1, number, arguments, ending);
			intent(out, intent, "}));");
		}
	}

	private static class ObjectArrayHandler implements Handler {

		private final String subType;

		public ObjectArrayHandler(String subType) {

			this.subType = subType;
		}

		@Override
		public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

			intent(out, intent, "remedium.setState(" + subType + ".createVectorConsumingState(remedium, message, function(" + name + number + ":Vector.<" + subType + ">):void {");
			generate(out, intent + 1, number, arguments, ending);
			intent(out, intent, "}));");
		}
	}

	private static final Map<String, Handler> HANDLERS = new HashMap<String, Handler>();

	static {

		HANDLERS.put("String", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeString(remedium, message, function(" + name + number + ":String):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("String[]", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeString(remedium, message, function(" + name + number + ":Vector.<String>):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("int", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeInt(remedium, message, function(" + name + number + ":int):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("int[]", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeIntArray(remedium, message, function(" + name + number + ":Vector.<int>):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("double", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeDouble(remedium, message, function(" + name + number + ":Number):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("double[]", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeDoubleArray(remedium, message, function(" + name + number + ":Vector.<Number>):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("byte", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeByte(remedium, message, function(" + name + number + ":int):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});

		HANDLERS.put("byte[]", new Handler() {

			@Override
			public void handle(PrintStream out, int intent, String name, int number, List<Argument> arguments, List<String> ending) {

				intent(out, intent, "RemediumTools.consumeByteArray(remedium, message, function(" + name + number + ":ByteArray):void {");
				generate(out, intent + 1, number, arguments, ending);
				intent(out, intent, "});");
			}
		});
	}

	public static void generate(PrintStream out, int intent, int number, List<Argument> arguments, List<String> ending) {

		if (arguments.isEmpty()) {
			for (String end : ending) {
				intent(out, intent, end);
			}
		} else {
			Argument a = arguments.get(0);
			String type = a.getClassName();
			Handler handler = HANDLERS.get(type);

			if (handler == null) {
				if (type.endsWith("[]")) {
					handler = new ObjectArrayHandler(type.substring(0, type.length() - 2));
				} else {
					handler = new ObjectHandler(type);
				}
			}

			handler.handle(out, intent, a.getName(), number, arguments.subList(1, arguments.size()), ending);
		}
	}

	private static void intent(PrintStream out, int intent, String s) {

		while (--intent >= 0) {
			out.print("\t");
		}
		out.println(s);
	}
}
